# -*- coding: utf-8 -*-
# pc上模拟执行
import logging
import os, time
import pickle
import timeit
import warnings
import requests

from main.audio_reader import Reader
from main.feature_engineer import FeatureEngineer

from main.majority_voter import MajorityVoter
from main.baby_cry_predictor import BabyCryPredictor

class Prediction:
    def __init__(self, audio_name: str = "Louise_01.m4a_2.wav"):
        # 上次哭声状态
        self.last_cry_state = -1
        # 上次哭声开始时间
        self.last_cry_start = int(round(time.time()))

        # Arguments
        self.file_name = audio_name
        self.load_path_data = os.path.normpath("./test")
        self.load_path_model = os.path.normpath("./output/model")
        self.save_path = os.path.normpath("./output/prediction")
        self.log_path = os.path.normpath("./logger")
        # Set up logging
        logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
                            datefmt='%Y-%m-%d %I:%M:%S %p',
                            filename=os.path.join(self.log_path, 'logs_prediction_test_test_model.log'),
                            filemode='w',
                            level=logging.INFO)
    
    def start(self):
        # READ RAW SIGNAL
        logging.info('Reading {0}'.format(self.file_name))
        start = timeit.default_timer()

        # Read signal (first 5 sec)
        file_reader = Reader(os.path.join(self.load_path_data, self.file_name))

        play_list = file_reader.read_audio_file()
        audio_data, sr = file_reader.read_audio_file()  # 解包返回值
        
        stop = timeit.default_timer()
        logging.info('Time taken for reading file: {0}'.format(stop - start))

        # 特征引擎
        logging.info('Starting feature engineering')
        start = timeit.default_timer()

        # 提取特征
        engineer = FeatureEngineer()

        play_list_processed = list()
        
        # 仅对音频数据调用 feature_engineer 函数
        tmp = engineer.feature_engineer(audio_data)
        play_list_processed.append(tmp)
        
        stop = timeit.default_timer()
        logging.info('Time taken for feature engineering: {0}'.format(stop - start))

        # 开始预测
        # https://stackoverflow.com/questions/41146759/check-sklearn-version-before-loading-model-using-joblib
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", category=UserWarning)

        with open((os.path.join(self.load_path_model, 'model.pkl')), 'rb') as fp:
            model = pickle.load(fp)

        predictor = BabyCryPredictor(model)

        predictions = list()

        for signal, _ in play_list_processed:
            tmp = predictor.classify(signal)
            predictions.append(tmp)
        
        # 解析预测结果
        self.getResult(p=predictions)
        
    
    def getResult(self, p):
        # 判断是否哭声
        majority_voter = MajorityVoter(p)
        majority_vote = majority_voter.vote()

        # 如果当前结果和上次不一致则状态发生改变，记录
        if self.last_cry_state != majority_vote:
            # 当前时间
            curr_cry_date = int(round(time.time()))
            cry_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(curr_cry_date))
            
            # 时长
            duration = curr_cry_date - self.last_cry_start
            
            # 预测结果
            pre_result = ""
            if majority_vote == 1:
                descr = "好宝👍👍👍" if duration > 60 * 30 else "😒😒😒"
                pre_result = pre_result + f"{cry_date} 开始哭闹😭，安静时长:{duration}s {descr}\n"
                # requests.get(url=f"https://api.day.app/oSiy4Mtp7WGTydYEvL7UtN/{pre_result}")
            else:
                descr = "😒😒😒" if duration > 60 * 30 else "好宝👍👍👍"
                pre_result = pre_result + f"{cry_date} 停止哭闹😊，哭闹时长:{duration}s\n"
                # requests.get(url=f"https://api.day.app/oSiy4Mtp7WGTydYEvL7UtN/{pre_result}")
            
            print(pre_result)
            
            # 写入结果prediction.txt
            with open(os.path.join(self.save_path, 'prediction.txt'), 'a', encoding='utf-8') as text_file:
                text_file.writelines(pre_result)
            
            # 更新状态改变时间点
            self.last_cry_start = int(round(time.time()))
        
        # 更新预测状态
        self.last_cry_state = majority_vote
                   
if __name__ == '__main__':
    p = Prediction()
    p.start()
